class MyPromise {
	static PENDING = 'PENDING' // 等待态
	static FULFILLED = 'FULFILLED' // 执行态
	static REJECTED = 'REJECTED' // 拒绝态

	constructor (executor) {
		if (typeof executor !== 'function') {
			throw new TypeError(`executor show is function`)
		}

		this.initValue() // 执行初始化值
		this.initBind() // 执行绑定this的函数

		try {
			executor(this.resolve, this.reject) // 执行executor函数并将resolve 和 reject 函数作为参数传递过去
		} catch (e) {
			this.reject(e)
		}
	}

	// 初始化值
	initValue () {
		this.value = null // 执行结果值
		this.reason = null // 拒因
		this.state = MyPromise.PENDING
		this.onFulfilledCallbacks = []
		this.onRejectedCallbacks = []
	}

	// 绑定 resolve 和 reject 函数的this指向
	initBind () {
		this.resolve = this.resolve.bind(this)
		this.reject = this.reject.bind(this)
	}

	// 解决函数
	resolve (value) {
		if (this.state === MyPromise.PENDING) {
			this.state = MyPromise.FULFILLED
			this.value = value
			this.onFulfilledCallbacks.forEach(fn => fn(this.value))
		}
	}

	// 拒绝函数
	reject (reason) {
		if (this.state === MyPromise.PENDING) {
			this.state = MyPromise.REJECTED
			this.reason = reason
			this.onRejectedCallbacks.forEach(fn => fn(this.reason))
		}
	}

	then (onFulfilled, onRejected) {
		if (typeof onFulfilled !== 'function') {
			onFulfilled = function (value) {
				return value
			}
		}
		if (typeof onRejected !== 'function') {
			onRejected = function (reason) {
				throw reason
			}
		}

		const promise2 = new MyPromise((resolve, reject) => {
			if (this.state === MyPromise.FULFILLED) {
				setTimeout(() => {
					try {
						const x = onFulfilled(this.value)
						MyPromise.resolvePromise(promise2, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}

			if (this.state === MyPromise.REJECTED) {
				setTimeout(() => {
					try {
						const x = onRejected(this.reason)
						MyPromise.resolvePromise(promise2, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}

			if (this.state === MyPromise.PENDING) {
				this.onFulfilledCallbacks.push((value) => {
					setTimeout(() => {
						try {
							const x = onFulfilled(value)
							MyPromise.resolvePromise(promise2, x, resolve, reject)
						} catch (e) {
							reject(e)
						}
					})
				})

				this.onRejectedCallbacks.push((reason) => {
					setTimeout(() => {
						try {
							const x = onRejected(reason)
							MyPromise.resolvePromise(promise2, x, resolve, reject)
						} catch (e) {
							reject(e)
						}
					})
				})
			}
		}) // promise2

		return promise2
		
	}
}
// MyPromise.resolvePromise = function(promise2, x, resolve, reject) {
//   // x 与 promise 相等
//   if (promise2 === x) {
//     reject(new TypeError('Chaining cycle detected for promise'))
//   }

//   let called = false
//   if (x instanceof MyPromise) {
//     // 判断 x 为 Promise
//     x.then(
//       value => {
//         MyPromise.resolvePromise(promise2, value, resolve, reject)
//       },
//       reason => {
//         reject(reason)
//       }
//     )
//   } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
//     // x 为对象或函数
//     try {
//       const then = x.then
//       if (typeof then === 'function') {
//         then.call(
//           x,
//           value => {
//             if (called) return
//             called = true
//             MyPromise.resolvePromise(promise2, value, resolve, reject)
//           },
//           reason => {
//             if (called) return
//             called = true
//             reject(reason)
//           }
//         )
//       } else {
//         if (called) return
//         called = true
//         resolve(x)
//       }
//     } catch (e) {
//       if (called) return
//       called = true
//       reject(e)
//     }
//   } else {
//     resolve(x)
//   }
// }

MyPromise.resolve = function(value){
  return new MyPromise(resolve => {
    resolve(value)
  })
}
MyPromise.reject = function(reason){
  return new MyPromise((resolve, reject) => {
    reject(reason)
  })
}
/*
all 方法，当所有的都promise都执行完，且没有 拒绝reject，按顺序返回结果数组
如果有一个出错，那么就调用reject方法，并将拒因返回
 */
MyPromise.all = function(promises){
  const values = []
  return new MyPromise((resolve, reject) => {
    promises.forEach(promise => {
      promise.then(value => {
        values.push(value)
        if (values.length === promises.length) {
          resolve(values)
        }
      }, reason => {
        reject(reason)
      })
    })
  })
}
MyPromise.race = function (promises) {
   const p = new MyPromise((resolve, reject) => {
    promises.forEach(promise => {
      promise.then(value => {
        resolve(value) // 执行成功
      }, reason => {
        reject(reason) // 执行拒绝
      })
    })
  })
   return p
}

MyPromise.resolvePromise = function (promise2, x, resolve, reject) {
	if (promise2 === x) {
		reject(new TypeError(`返回实例与本实例相同`)) 
	}

	let called = false
	if (x instanceof MyPromise) {
		x.then(value => {
			MyPromise.resolvePromise(promise2, value, resolve, reject)
		}, reason => {
			reject(reason)
		})
	}

	else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
		try {
			const then = x.then
			if (typeof then === 'function') {
				then.call(x, value => {
					if (called) return
					called = true
					MyPromise.resolvePromise(promise2, value, resolve, reject)
				}, reason => {
					if (called) return
					called = true
					reject(reason)
				})
			} else {
				if (called) return
				called = true
				resolve(x)
			}
		} catch (e) {
			if (called) return
			called = true
			reject(e)
		}
	}
	else {
		resolve(x)
	}
}

MyPromise.defer = MyPromise.deferred = function() {
  let dfd = {}
  dfd.promise = new MyPromise((resolve, reject) => {
    dfd.resolve = resolve
    dfd.reject = reject
  })
  return dfd
}
module.exports = MyPromise